#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <time.h>

using namespace std;

#define THREAD_NUM 3

int n = 1000;

class ThreadArg  // 通过自定义类型的方式将局部(主线程)定义的互斥锁对象传给每个新线程
{
public:
    ThreadArg(const string& name, pthread_mutex_t* mtx)
    :_mtx(mtx), _name(name)
    {}

    pthread_mutex_t* _mtx;
    string _name;
};

void* threadRun(void* arg)
{
    ThreadArg* ta = (ThreadArg*)arg;
    while (true)
    {
        pthread_mutex_lock(ta->_mtx);  // 即将进入临界区，进行加锁
        if (n > 0)
        {
            usleep(rand() % 1500);
            cout << ta->_name << "线程抢到一张票啦" << n << endl;
            n--;  // 访问修改共享资源
            pthread_mutex_unlock(ta->_mtx);  // 解锁
        }
        else
        {
            pthread_mutex_unlock(ta->_mtx);  // 解锁 注意不满足需要到这里进行解锁
            break;
        } 

        usleep(rand() % 2000);  // 模拟执行其他任务
    }
    delete ta;  // 别忘了释放空间
    return nullptr;
}

int main()
{
    pthread_mutex_t mtx;  // 定义局部锁对象
    pthread_mutex_init(&mtx, nullptr);  // 局部锁对象需要调用初始化接口

    srand((unsigned long)time(nullptr));
    pthread_t tid[THREAD_NUM];
    string ar[THREAD_NUM];
    for (int i = 0; i < THREAD_NUM; ++i)
    {
        ar[i] = "thread-";
        ar[i] += to_string(i + 1);
        ThreadArg* ta = new ThreadArg(ar[i], &mtx);
        pthread_create(tid + i, nullptr, threadRun, (void*)ta);
    }

    // 主线程阻塞等待新线程
    for (int i = 0; i < THREAD_NUM; ++i)
    {
        pthread_join(tid[i], nullptr);
    }

    pthread_mutex_destroy(&mtx);  // 对锁对象进行摧毁，释放
    return 0;
}

// pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;  // 全局属性的互斥锁变量，可以直接进行初始化
// int n = 1000;

// void* threadRun(void* arg)
// {
//     while (true)
//     {
//         pthread_mutex_lock(&mtx);  // 即将进入临界区，进行加锁
//         if (n > 0)
//         {
//             usleep(rand() % 1500);
//             cout << (char*)arg << "线程抢到一张票啦" << n << endl;
//             n--;  // 访问修改共享资源
//             pthread_mutex_unlock(&mtx);  // 解锁
//         }
//         else
//         {
//             pthread_mutex_unlock(&mtx);  // 解锁 注意不满足需要到这里进行解锁
//             break;
//         } 

//         usleep(rand() % 2000);  // 模拟执行其他任务
//     }
//     return nullptr;
// }

// int main()
// {
//     srand((unsigned long)time(nullptr));
//     pthread_t tid[THREAD_NUM];
//     string ar[THREAD_NUM];
//     for (int i = 0; i < THREAD_NUM; ++i)
//     {
//         ar[i] = "thread-";
//         ar[i] += to_string(i + 1);
//         pthread_create(tid + i, nullptr, threadRun, (void*)ar[i].c_str());
//     }

//     // 主线程阻塞等待新线程
//     for (int i = 0; i < THREAD_NUM; ++i)
//     {
//         pthread_join(tid[i], nullptr);
//     }

//     pthread_mutex_destroy(&mtx);  // 对锁对象进行摧毁，释放
//     return 0;
// }